#pragma once
#include <iostream>
#include <unordered_map>
#include <vector>
#include <assert.h>
#include <mutex>
#include <mysql/mysql.h>

#include "../com/util.hpp"
#include "../com/log.hpp"
namespace lh_model
{
    using namespace lh_util;
    using namespace lh_log;
    static std::string host_conf = "./conf/hostlist.conf";
    struct Question
    {
        std::string number; // 题目编号
        std::string title;  // 题目名称
        std::string level;  // 题目难度等级
        int climit;         // 题目时间限制
        int mlimit;         // 题目空间限制
        std::string desc;   // 题目描述
        std::string header; // 题目预设值代码
        std::string tail;   // 题目运行代码
    };

    static const std::string host = "127.0.0.1";
    static const std::string user = "lxb";
    static const std::string password = "hxr040920";
    static const std::string tb_name = "questions";
    static const std::string db_name = "oj";
    static const int port = 3306;
    class Model
    {
    public:
        Model()
        {
        }
        ~Model() {}
        bool QuerySql(const std::string &sql, std::vector<Question> *out)
        {
            MYSQL *my = mysql_init(nullptr);
            if (mysql_real_connect(my, host.c_str(), user.c_str(), password.c_str(), db_name.c_str(), port, nullptr, 0) == nullptr)
            {
                LOG(FATAL) << "msyql connect err" << "\n";
                return false;
            }
            // 执行
            if (mysql_query(my, sql.c_str()) != 0)
            {
                LOG(ERROR) << "mysql query err: " << mysql_error(my);
                mysql_close(my);
                return false;
            }
            mysql_set_character_set(my,"utf8");
            // 获取结果
            MYSQL_RES *res = mysql_store_result(my);
            if (res == nullptr)
            {
                LOG(ERROR) << "mysql store result failed: " << mysql_error(my);
                mysql_close(my);
                return false;
            }
            // 行数
            int rows = mysql_num_rows(res);
            // 列数
            int cols = mysql_num_fields(res);
            for (int i = 0; i < rows; i++)
            {
                // 获取一行数据
                MYSQL_ROW row = mysql_fetch_row(res);
                Question q;
                q.number = row[0];
                q.title = row[1];
                q.level = row[2];
                q.desc = row[3];
                q.header = row[4];
                q.tail = row[5];
                q.climit = atoi(row[6]);
                q.mlimit = atoi(row[7]);
                out->push_back(q);
            }

            mysql_close(my);

            return true;
        }
        bool GetAllQuestion(std::vector<Question> *questions)
        {
            std::string sql = "select * from ";
            sql += tb_name;
            sql += ";";
            return QuerySql(sql, questions);
        }
        bool GetQuestionByNumber(const std::string &number, Question *question)
        {
            std::string sql = "select * from ";
            sql += tb_name;
            sql += " where id=";
            sql += number;
            std::vector<Question> out;
            if (QuerySql(sql, &out) == false)
                return false;
            *question = out[0];
            return true;
        }

    private:
        std::unordered_map<std::string, Question> _questions;
    };
}